import 'dart:io';

import 'package:built_collection/built_collection.dart';
import 'package:learning_content_admin_pannel.core/core/domain/repositories/lexical_item_image_repository/repository.dart';

class ImageRepositoryImpl implements ImageRepository {
  ImageRepositoryImpl({
    required String documentDirectoryPath,
  }) {
    final imageDirectoryPath = '$documentDirectoryPath/images';

    _imageDirectory = Directory(imageDirectoryPath);

    if (!_imageDirectory.existsSync()) {
      _imageDirectory.createSync();
    }
  }

  late final Directory _imageDirectory;

  @override
  Future<BuiltMap<String, String>> getCachedImagePathMap() async {
    final cachedImagePaths = <String, String>{};

    final imageFileStream = _getImageFileStream();

    await for (final imageFile in imageFileStream) {
      final imageFileName = imageFile.path.replaceFirst(RegExp('.*/'), '');
      final imageId = imageFileName.substring(0, imageFileName.length - '.jpg'.length);
      final imagePath = _getImagePathFromId(imageId);
      cachedImagePaths[imageId] = imagePath;
    }

    return cachedImagePaths.build();
  }

  @override
  Future<int> computeCacheSize() async {
    var cacheSizeInBytes = 0;

    final imageFileStream = _getImageFileStream();

    await for (final imageFile in imageFileStream) {
      cacheSizeInBytes += await imageFile.length();
    }

    return cacheSizeInBytes;
  }

  @override
  Future<void> clearCache() async {
    final fileSystemEntityStream = _imageDirectory.list();

    await for (final fileSystemEntity in fileSystemEntityStream) {
      await fileSystemEntity.delete(recursive: true);
    }
  }

  @override
  Future<String?> cacheImage({
    required String imageId,
    required List<int> imageBytes,
  }) async {
    try {
      final imagePath = _getImagePathFromId(imageId);
      final imageFile = File(imagePath);
      await imageFile.create(recursive: true);
      await imageFile.writeAsBytes(imageBytes);
      return imagePath;
    } catch (_) {
      return null;
    }
  }

  Stream<File> _getImageFileStream() {
    return _imageDirectory.list(recursive: true).where((fileSystemEntity) {
      if (fileSystemEntity is! File) {
        return false;
      }

      final file = fileSystemEntity;
      return file.path.endsWith('.jpg');
    }).map((fileSystemEntity) {
      return fileSystemEntity as File;
    });
  }

  String _getImagePathFromId(String imageId) {
    return '${_imageDirectory.path}/${imageId.substring(0, 2)}/$imageId.jpg';
  }
}
